﻿using Common.Core.Attributes;
using Common.Core.Common;
using Common.Core.Encrypt;
using Common.Core.Enums;
using Common.Core.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Configuration;
using System.Reflection;

namespace Common.Core.Data
{
    /// <summary>
    /// 数据库服务提供者，支持读写分离
    /// </summary>
    public class DBServerProvider
    {
        /// <summary>
        /// 数据库配置名称
        /// </summary>
        private static string dbConfigName = "";

        #region 非注入方式
        /// <summary>
        /// 获取SqlSugar版本数据库连接
        /// </summary>
        /// <typeparam name="TEntity">实体，主要获取库名</typeparam>
        /// <returns></returns>
        public static DbConnections GetDBConnection<TEntity>()
        {
            dbConfigName = typeof(TEntity).GetCustomAttribute<AppDBContextAttribute>(false)?.DbConfigName ?? dbConfigName;

            return GetDBConnection(dbConfigName);
        }

        /// <summary>
        /// 获取SqlSugar版本数据库连接
        /// </summary>
        /// <param name="_dbConfigName">数据库节点名称（DbConnections:XXXXXXXX）</param>
        /// <returns></returns>
        public static DbConnections GetDBConnection(string _dbConfigName)
        {
            bool conStringEncrypt = Configs.GetConfigurationValue("DbConnections", "ConStringEncrypt").ToBool();

            if (string.IsNullOrEmpty(dbConfigName))
            {
                dbConfigName = Configs.GetConfigurationValue("DbConnections", "DefaultDataBase");
            }
            if (string.IsNullOrEmpty(dbConfigName))
            {
                throw new ConfigurationErrorsException("指定数据库节点和默认数据库节点都为空！请检查dbConfigName是否指定节点或DefaultDataBase是否配置默认节点。");
            }

            var masterDBValue = Configs.GetSection($"DbConnections:{dbConfigName}:MasterDB");
            if (string.IsNullOrEmpty(masterDBValue["ConnectionString"]))
            {
                throw new ConfigurationErrorsException($"数据库节点主库连接为空！请检查 [{dbConfigName}] 是否配置数据库节点");
            }

            DbConnections dbConnections = new DbConnections();

            // 主库
            DbConnectionOptions dbConnectionOptions = new DbConnectionOptions();
            dbConnectionOptions.ConnectionString = Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "ConnectionString");
            dbConnectionOptions.DatabaseType = (DatabaseType)Enum.Parse(typeof(DatabaseType), Configs.GetConfigurationValue("DbConnections:" + dbConfigName + ":MasterDB", "DatabaseType"));
            if (conStringEncrypt)
            {
                dbConnectionOptions.ConnectionString = DEncrypt.Decrypt(dbConnectionOptions.ConnectionString);
            }
            dbConnections.MassterDB = dbConnectionOptions;

            // 读写分离
            bool isDBReadWriteSeparate = Configs.GetConfigurationValue("DbConnections", "IsDBReadWriteSeparate").ToBool();
            dbConnections.IsDBReadWriteSeparate = isDBReadWriteSeparate;

            // 是否开启sql输出，默认输出(true)
            bool printSqlLog = Configs.GetConfigurationValue("DbConnections", "PrintSqlLog").ToBool(true);
            dbConnections.PrintSqlLog = printSqlLog;
            // 是否开启无参数化SQL输出（大部分情况单独开启PrintSqlLog即可），目前可以应用于SqlSugar调式模式，默认不输出
            bool printDebugSqlLog = Configs.GetConfigurationValue("DbConnections", "PrintDebugSqlLog").ToBool();
            dbConnections.PrintDebugSqlLog = printDebugSqlLog;

            if (isDBReadWriteSeparate)
            {
                Dictionary<string, DbConnectionOptions> dictRead = Configs.GetSection("DbConnections:" + dbConfigName + ":ReadDb").Get<Dictionary<string, DbConnectionOptions>>();
                List<DbConnectionOptions> readList = new List<DbConnectionOptions>();

                string queryDBStrategy = Configs.GetConfigurationValue("DbConnections", "QueryDBStrategy");
                if (queryDBStrategy == "Random")//随机策略
                {
                }
                else if (queryDBStrategy == "Polling")//轮询策略
                {
                }
                else //权重策略
                {
                    foreach (var item in dictRead)
                    {
                        readList.Add(item.Value);
                    }
                }

                dbConnections.ReadDB = readList;
            }

            return dbConnections;
        }

        #endregion

        #region 容器注入
        /// <summary>
        /// 根据数据库节点名称获取SqlSugar版本数据库连接
        /// </summary>
        /// <param name="services">容器</param>
        /// <param name="_dbConfigName">数据库节点名称（DbConnections:XXXXXXXX）</param>
        /// <returns></returns>
        public static DbConnections GetDBConnection(IServiceCollection services, string _dbConfigName)
        {
            dbConfigName = _dbConfigName;
            return GetDBConnection(services);
        }

        /// <summary>
        /// 获取SqlSugar版本数据库连接
        /// </summary>
        /// <param name="services">容器</param>
        /// <returns></returns>
        public static DbConnections GetDBConnection(IServiceCollection services)
        {
            IConfiguration configuration = services.BuildServiceProvider().GetService<IConfiguration>();

            bool conStringEncrypt = configuration.GetSection("DbConnections")["ConStringEncrypt"].ToBool();
            if (string.IsNullOrEmpty(dbConfigName))
            {
                dbConfigName = configuration.GetSection("DbConnections")["DefaultDataBase"];
            }
            if (string.IsNullOrEmpty(dbConfigName))
            {
                throw new ConfigurationErrorsException("默认数据库节点为空！请检查DefaultDataBase是否配置默认节点或dbConfigName是否指定节点。");
            }

            var masterDBValue = configuration.GetSection($"DbConnections:{dbConfigName}:MasterDB");
            if (string.IsNullOrEmpty(masterDBValue["ConnectionString"]))
            {
                throw new ConfigurationErrorsException($"数据库节点主库连接为空！请检查 [{dbConfigName}] 是否配置数据库节点");
            }

            DbConnections dbConnections = new DbConnections();

            // 主库
            DbConnectionOptions dbConnectionOptions = new DbConnectionOptions();
            dbConnectionOptions.ConnectionString = masterDBValue["ConnectionString"];
            dbConnectionOptions.DatabaseType = (DatabaseType)Enum.Parse(typeof(DatabaseType), masterDBValue["DatabaseType"]);
            if (conStringEncrypt)
            {
                dbConnectionOptions.ConnectionString = DEncrypt.Decrypt(dbConnectionOptions.ConnectionString);
            }
            dbConnections.MassterDB = dbConnectionOptions;

            // 读写分离
            bool isDBReadWriteSeparate = configuration.GetSection("DbConnections")["IsDBReadWriteSeparate"].ToBool();
            dbConnections.IsDBReadWriteSeparate = isDBReadWriteSeparate;

            // 是否开启常规SQL输出（即原始ORM支持的SQL模式），默认输出(true)
            bool printSqlLog = configuration.GetSection("DbConnections")["PrintSqlLog"].ToBool(true);
            dbConnections.PrintSqlLog = printSqlLog;
            // 是否开启无参数化SQL输出（大部分情况单独开启PrintSqlLog即可），目前可以应用于SqlSugar调式模式，默认不输出
            bool printDebugSqlLog = configuration.GetSection("DbConnections")["PrintDebugSqlLog"].ToBool();
            dbConnections.PrintDebugSqlLog = printDebugSqlLog;

            if (isDBReadWriteSeparate)
            {
                Dictionary<string, DbConnectionOptions> dictRead = configuration.GetSection("DbConnections:" + dbConfigName + ":ReadDb").Get<Dictionary<string, DbConnectionOptions>>();
                List<DbConnectionOptions> readList = new List<DbConnectionOptions>();

                string queryDBStrategy = configuration.GetSection("DbConnections")["QueryDBStrategy"];
                if (queryDBStrategy == "Random")//随机策略
                {
                }
                else if (queryDBStrategy == "Polling")//轮询策略
                {
                }
                else //权重策略
                {
                    foreach (var item in dictRead)
                    {
                        readList.Add(item.Value);
                    }
                }

                dbConnections.ReadDB = readList;
            }

            return dbConnections;
        }
        #endregion
    }

    /// <summary>
    /// 定义主数据和从数据库配置选项
    /// </summary>
    public class DbConnections
    {
        /// <summary>
        /// 主数据库
        /// </summary>
        public DbConnectionOptions MassterDB { get; set; }

        /// <summary>
        /// 是否启用读写分离
        /// </summary>
        public bool IsDBReadWriteSeparate { get; set; }
        /// <summary>
        /// 是否开启常规SQL输出（即原始ORM支持的SQL模式），默认输出(true)
        /// </summary>
        public bool PrintSqlLog { get; set; }
        /// <summary>
        /// 是否开启无参数化SQL输出（大部分情况单独开启PrintSqlLog即可），目前可以应用于SqlSugar调式模式，默认不输出
        /// </summary>
        public bool PrintDebugSqlLog { get; set; }
        /// <summary>
        /// 从数据库
        /// </summary>
        public List<DbConnectionOptions> ReadDB { get; set; }
    }


    /// <summary>
    /// 数据库配置选项,定义数据库连接字符串、数据库类型和访问权重
    /// </summary>
    public class DbConnectionOptions
    {
        /// <summary>
        /// 数据库连接字符
        /// </summary>
        public string ConnectionString { get; set; }

        /// <summary>
        /// 数据库类型
        /// </summary>
        public DatabaseType DatabaseType { get; set; }

        /// <summary>
        /// 访问权重，值越大权重越低
        /// </summary>
        public int DbLevel { get; set; }
    }
}
